// TemplatesC++.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>

using namespace std;


// Here we define a sorter class that sorts T types
// template, <data type>, class name
template<class T> class Sorter
{

	// Default a class variable is private
	T Data;
public:

	T Value;
	

	// Default constructor
	Sorter() 
	{
		cout << "Created sorter" << endl;
	}

	// Setter, this is also a member function of the class
	// It takes the T data type and this depends on the object that is created 
	// with the specified data type
	void SetData(T nValue)
	{
		Data = nValue;
	}

	// Getter
	T GetData() const
	{
		return Data;
	}

	void PrintData()
	{
		cout << Data;
	}
};


// Template function
// template keyword, <data type>, return type, function name with data type parameter
// This function can be used to create with several data types like integer and double
// This way we use generic programming to code only the functionality and making it not 
// data type specific
template<class TYPE> void PrintTwice(TYPE data)
{
	cout << "Twice: " << data * 2 << endl;
}


int _tmain(int argc, _TCHAR* argv[])
{

	// Create a Sorter object with the integer data type
	// IntSorter is a object that is created on the stack
	Sorter<int> IntSorter;

	// Create pointer to reference a object (it's called a reference variable), the pointer is created on the stack
	// it points to the object that is assigned to it with the "new" keyword (this creates a object on the heap)
	// This object is created on the heap, so the pointer contains a memory address that points
	// to the actual object on the heap
	Sorter<int> *IntSorter2;

	// Create the actual object on the heap and assign the memory address to the pointer
	// The pointer now points to the object on the heap
	IntSorter2 = new Sorter<int>;

	int Result = 0;
	double ResultDouble = 40.00;

	IntSorter.SetData(10);
	Result = IntSorter.GetData();

	IntSorter.Value = 20;

	cout << "Result: " << Result << endl;

	IntSorter.PrintData();

	// Do the same for the object that is created on the heap
	// We use the reference variable (pointer) to acces the object on the heap
	IntSorter2->SetData(10);
	Result = IntSorter2->GetData();

	IntSorter2->Value = 20;

	cout << "Result: " << Result << endl;

	IntSorter2->PrintData();

	// Here we use two diffrent data types for in two calls
	PrintTwice(IntSorter.Value);
	PrintTwice(ResultDouble);

	return 0;
}

